package config

import (
	"os"
	"path/filepath"
	"time"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
)

func InitLogger(cfg *LogConfig) (*zap.Logger, error) {
	// 确保日志目录存在
	if err := os.MkdirAll(cfg.Path, 0755); err != nil {
		return nil, err
	}

	// 设置日志级别
	var level zapcore.Level
	switch cfg.Level {
	case "debug":
		level = zapcore.DebugLevel
	case "info":
		level = zapcore.InfoLevel
	case "warn":
		level = zapcore.WarnLevel
	case "error":
		level = zapcore.ErrorLevel
	default:
		level = zapcore.InfoLevel
	}

	// 创建编码器配置
	encoderConfig := zap.NewProductionEncoderConfig()
	encoderConfig.TimeKey = "time"
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
	encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder

	// 创建多个输出核心
	cores := []zapcore.Core{}

	// 文件输出核心
	fileCore := createFileCore(cfg, encoderConfig, level)
	cores = append(cores, fileCore)

	// 控制台输出核心（开发环境）
	if cfg.Level == "debug" {
		consoleCore := createConsoleCore(encoderConfig, level)
		cores = append(cores, consoleCore)
	}

	// 创建核心
	core := zapcore.NewTee(cores...)

	// 创建日志记录器
	logger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1))

	return logger, nil
}

func createFileCore(cfg *LogConfig, encoderConfig zapcore.EncoderConfig, level zapcore.Level) zapcore.Core {
	// 创建日志写入器
	lumberjackLogger := &lumberjack.Logger{
		Filename:   filepath.Join(cfg.Path, "chicory.log"),
		MaxSize:    100, // MB
		MaxBackups: 30,
		MaxAge:     cfg.MaxAge,
		Compress:   false,
		LocalTime:  true,
	}

	// 设置日志轮转
	go func() {
		ticker := time.NewTicker(time.Duration(cfg.RotationTime) * time.Hour)
		defer ticker.Stop()

		for range ticker.C {
			lumberjackLogger.Rotate()
		}
	}()

	return zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderConfig),
		zapcore.AddSync(lumberjackLogger),
		level,
	)
}

func createConsoleCore(encoderConfig zapcore.EncoderConfig, level zapcore.Level) zapcore.Core {
	// 控制台输出使用Console编码器
	consoleEncoder := zapcore.NewConsoleEncoder(encoderConfig)
	return zapcore.NewCore(
		consoleEncoder,
		zapcore.AddSync(os.Stdout),
		level,
	)
}
